/* eslint indent: ["off"] */
/* eslint space-before-function-paren: ["off"] */

// 马尔科夫链（Markov Chain）算法

// 引入 lodash 库，用于数据处理和操作
const _ = require('lodash')
// 精确计算
const NP = require('number-precision')
// 引入 path 模块，用于处理文件和目录路径
const path = require('path')
// 获取项目根目录
const ROOT_DIR = path.join(__dirname, '..')
// helpers 目录
const HELPERS_DIR = path.join(ROOT_DIR, 'helpers')

// 补齐单个值
const { padSingleValue } = require(path.join(HELPERS_DIR, 'utils.js'))

// 读取所有数据
let { allValues } = require(path.join(HELPERS_DIR, 'readAllValues.js'))

// 构建转移矩阵
function buildTransitionMatrix(data) {
  const transitionMatrix = {}

  // 遍历历史数据，构建转移矩阵
  for (let i = 0; i < data.length - 1; i++) {
    const currentNumber = data[i].number
    const nextNumber = data[i + 1].number

    if (!transitionMatrix[currentNumber]) {
      transitionMatrix[currentNumber] = {}
    }

    if (!transitionMatrix[currentNumber][nextNumber]) {
      transitionMatrix[currentNumber][nextNumber] = 0
    }

    transitionMatrix[currentNumber][nextNumber]++
  }

  // 归一化转移矩阵
  Object.keys(transitionMatrix).forEach((currentNumber) => {
    const totalTransitions = Object.values(transitionMatrix[currentNumber]).reduce((sum, count) => sum + count, 0)

    Object.keys(transitionMatrix[currentNumber]).forEach((nextNumber) => {
      transitionMatrix[currentNumber][nextNumber] /= totalTransitions
    })
  })

  return transitionMatrix
}

// 打印转移矩阵
// console.log('转移矩阵:', transitionMatrix)

function getHistory(year) {
  return new Promise((resolve, reject) => {
    fetch(`https://history.macaumarksix.com/history/macaujc2/y/${year}`)
      .then((response) => response.json()) // 解析响应为 JSON
      .then((res) => {
        const list = res.data.reverse().map((item) => {
          return {
            number: item.openCode.match(/(\d+)$/)[0],
            time: item.openTime.match(/^\d{4}-\d{2}-\d{2}/)[0]
          }
        })
        resolve(list)
      })
  })
}
// 226(226), 591, 956, 1321, 1686, 2051
const historyYears = [2020, 2021, 2022, 2023, 2024, 2025]

const main = async () => {
  const history = await Promise.all(historyYears.map(getHistory))
  const historyData = history.flat()
  // console.log(historyData.length) // 1321, 956

  // const transitionMatrix = buildTransitionMatrix(historyData)
  // console.log(transitionMatrix)

  calculateAccuracy(historyData)
}

const calculateAccuracy = (historyData) => {
  const prefixLength = 226 + 365 * 3
  // const accuracy =
  // console.log(historyData.length) // 2051, 1686, 1321, 956, 591, 226
  const prefixData = historyData.slice(0, prefixLength)
  const suffixData = historyData.slice(prefixLength)

  const accuracyList = suffixData.map((item, index) => {
    const lastNumber = prefixData[prefixData.length - 1].number
    const padLastNumber = padSingleValue(lastNumber)

    const transitionMatrix = buildTransitionMatrix(prefixData)
    let transitionMatrixList = Object.keys(transitionMatrix[padLastNumber])

    if (transitionMatrixList.length > 32) {
      transitionMatrixList = transitionMatrixList.slice(0, 32)
    } else if (transitionMatrixList.length < 32) {
      // console.log(transitionMatrixList.length)
      const lastNumber2 = prefixData[prefixData.length - 2].number
      const padLastNumber2 = padSingleValue(lastNumber2)

      const transitionMatrix2 = buildTransitionMatrix(prefixData)
      const transitionMatrixList2 = Object.keys(transitionMatrix2[padLastNumber2])
      const count = 32 - transitionMatrixList.length
      transitionMatrixList = transitionMatrixList.concat(transitionMatrixList2.slice(0, count))
    }
    const accuracy = transitionMatrixList.map(Number).includes(Number(item.number)) ? 1 : 0

    prefixData.push(item)

    return {
      ...item,
      accuracy
    }
  })

  // console.log(accuracyList.map((item) => item.accuracy))

  const accuracy = accuracyList.map((item) => item.accuracy)
  console.log(accuracy)

  const accuracyCount = _.countBy(accuracy)
  console.log(accuracyCount)

  const successRate = NP.times(NP.round(NP.divide(accuracyCount[1], accuracy.length), 2), 100)

  console.log(`${accuracyCount[1]} / ${accuracy.length} = ${successRate}%`)
}

main()
